package com.bsoft.gol.hcb.service.feedback.service.impl;

import com.bsoft.gol.hcb.service.feedback.bean.request.AddFeedbackReq;
import com.bsoft.gol.hcb.service.feedback.dao.BaseFeedbackDAO;
import com.bsoft.gol.hcb.service.feedback.dao.DocTeamFeedbackTypeDAO;
import com.bsoft.gol.hcb.service.feedback.entity.BaseFeedback;
import com.bsoft.gol.hcb.service.feedback.service.IFeedbackService;
import com.bsoft.gol.hcb.utils.CommonUtils;
import com.bsoft.gol.hcb.utils.DateUtils;
import com.bsoft.gol.hcb.utils.PublicBusinessConst;
import com.bsoft.gol.mpi.model.Certificate;
import com.bsoft.gol.mpi.model.Unique;
import com.bsoft.gol.mpi.provider.IMPIProvider;
import com.bsoft.gol.mpi.service.MPIException;
import com.github.pagehelper.PageInfo;
import com.security.cipher.sm.SM4Utils;
import ctd.access.AccessToken;
import ctd.access.loader.AccessTokenLoader;
import ctd.account.AccountCenter;
import ctd.account.UserRoleToken;
import ctd.account.user.User;
import ctd.controller.exception.ControllerException;
import ctd.spring.boot.annotation.SsdevReference;
import ctd.spring.boot.annotation.SsdevService;
import ctd.util.AppContextHolder;
import ctd.util.JSONUtils;
import ctd.util.annotation.RpcService;
import hcn.annotation.UserEventTracking;
import hcn.bean.PushMessageBean;
import hcn.bean.feedback.qo.FeedbackListReq;
import hcn.docteam.DocTeamMemberEntity;
import hcn.enums.CollectionInfoIdTypeEnum;
import hcn.enums.CollectionInfoTypeEnum;
import hcn.service.commonclinical.qo.ParamsOrgQo;
import hcn.util.IdentityTransformUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.atag.core.exception.ServiceException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import pcn.sign.DoctInfo;
import service.rpc.AppMsgMqIntf;
import service.rpc.DoctorInfoServiceIntf;
import service.rpc.MessageSyncIntf;
import service.rpc.OrganizationInfoIntf;

import java.util.*;

/**
 * @Author:FangZhiyi
 * @Description
 * @Data Created in 2020/8/20 11:31
 * @Moddified By:
 */
@Slf4j
@SsdevService("feedback")
public class FeedbackServiceImpl implements IFeedbackService {

    @Autowired
    private BaseFeedbackDAO baseFeedbackDAO;

    @Autowired
    private DocTeamFeedbackTypeDAO docTeamFeedbackTypeDAO;

    @Autowired
    private MessageSyncIntf messageSyncService;

    @Autowired
    private DoctorInfoServiceIntf doctorInfoService;

    @Autowired
    private OrganizationInfoIntf organizationInfoService;
    @Autowired
    private AppMsgMqIntf appMsgMqIntf;
    @Value("${base_dist_url}")
    private String baseDistUrl;
    private String PROJECT_SOURCE = "GOL";
    @SsdevReference("gol-mpi.mpiProvider")
    private IMPIProvider mpiProvider;
    @Value("${sugg_tobe_repl_dist_url}")
    private String suggTobeReplDistUrl;

    /*新增投诉建议（问题反馈）*/
    @RpcService
    @Override
    @UserEventTracking(type1 = CollectionInfoTypeEnum.BASE_INFO,group1 = {CollectionInfoIdTypeEnum.PHONE_NO},
            type5 = CollectionInfoTypeEnum.J_BASE_INFO,group5 = {CollectionInfoIdTypeEnum.J_PHONE_NO})
    public BaseFeedback addFeedback(AddFeedbackReq addFeedbackReq) throws Exception {

        if (addFeedbackReq.getPhoneFollowUpFlag() == 1 && StringUtils.isEmpty(addFeedbackReq.getPhoneNo())) {
            throw new ServiceException("接受电话回访时，回访电话不能为空");
        }
        BaseFeedback baseFeedback = new BaseFeedback();
        BeanUtils.copyProperties(addFeedbackReq, baseFeedback);
        baseFeedback.setFeedbackId(UUID.randomUUID().toString().replace("-", ""));
        //未处理
        baseFeedback.setStatus("0");
        baseFeedback.setGmtCreate(new Date());
        baseFeedbackDAO.save(baseFeedback);


        List<DocTeamMemberEntity> doctorList = docTeamFeedbackTypeDAO.getDoctorList(addFeedbackReq.getClassify());

        if (CollectionUtils.isNotEmpty(doctorList)) {
            List<String> doctorIds = new ArrayList<>();
            for (DocTeamMemberEntity doc : doctorList) {
                if(doctorIds.contains(doc.getDoctorId())){
                    continue; // 医生多团队去重
                } else {
                    doctorIds.add(doc.getDoctorId());
                }
                String userId = doctorInfoService.getDoctorUserId(doc.getDoctorId());
                //推送极光消息
                PushMessageBean pushMessageRequest = new PushMessageBean();
                pushMessageRequest.setRoleId("doctor");
                pushMessageRequest.setMsgTitle("您有新的一条意见反馈待处理信息");
                pushMessageRequest.setUserId(userId);
                pushMessageRequest.setTemplateCode("SUGG_TOBE_COMMIT");
                pushMessageRequest.setNotificateType("sugg_tobe_commit");
                Map<String, String> variableMap = new HashMap<>();
                variableMap.put("jiguang", "极光消息");
                String docName = "";
                if (CommonUtils.isNotEmpty(userId)) {
                    DoctInfo doctInfo = doctorInfoService.getDoctorByUserId(userId);
                    if (CommonUtils.isNotEmpty(doctInfo)) {
                        docName = doctInfo.getName();
                    }
                }
                variableMap.put("#医生姓名#", CommonUtils.isEmpty(docName) == true ? doc.getDoctorName() : docName);
                variableMap.put("#意见反馈id#", baseFeedback.getFeedbackId());
                pushMessageRequest.setMsgVariableMap(variableMap);
                Map ext = new HashMap();
                ext.put("feedbackId", baseFeedback.getFeedbackId());
                pushMessageRequest.setExtras(ext);

                messageSyncService.productionMessage(pushMessageRequest);
            }
        }
        return baseFeedback;
    }

    /*回复处理投诉建议*/
    @RpcService
    @Override
    public BaseFeedback replyFeedback(AddFeedbackReq replyFeedbackReq) throws Exception {
        BaseFeedback baseFeedback = baseFeedbackDAO.get(replyFeedbackReq.getFeedbackId());
        if (baseFeedback == null) {
            throw new ServiceException("主键为:" + baseFeedback.getFeedbackId() + "的问题反馈记录不存在，无法回复，请查证");
        }
        //已处理
        if ("1".equals(baseFeedback.getStatus())) {
            throw new ServiceException("主键为:" + baseFeedback.getFeedbackId() + "的问题反馈记录已回复，请勿重复回复");
        }
        baseFeedback.setReplyUserId(replyFeedbackReq.getReplyUserId());
        baseFeedback.setReplyUserName(replyFeedbackReq.getReplyUserName());
        baseFeedback.setReplyContent(replyFeedbackReq.getReplyContent());
        baseFeedback.setStatus("1");
        baseFeedback.setReplyTime(new Date());
        baseFeedback.setGmtModified(new Date());
        baseFeedbackDAO.update(baseFeedback);

        Date date = new Date();
        PushMessageBean pushMessageRequest = new PushMessageBean();
        pushMessageRequest.setRoleId("patient");
        Map<String, String> variableMap = new HashMap<>();
        variableMap.put("jiguang", "极光消息");
        variableMap.put("#回复内容#", replyFeedbackReq.getReplyContent());
        variableMap.put("#回复时间#", "--");
        variableMap.put("#备注#", replyFeedbackReq.getContent());
        variableMap.put("#ReplyContent#", replyFeedbackReq.getReplyContent());
        variableMap.put("#ReplyTime#", DateUtils.toString(date,"yyyy-MM-dd HH:mm:ss"));
        variableMap.put("#Remarks#", baseFeedback.getContent());
        variableMap.put("#Title#", replyFeedbackReq.getReplyContent());
        variableMap.put("#Number#", baseFeedback.getFeedbackId());//编号
        variableMap.put("#Content#", replyFeedbackReq.getReplyContent());//内容
        variableMap.put("#Time#", DateUtils.toString(baseFeedback.getReplyTime(),"yyyy-MM-dd HH:mm:ss"));//时间
        //备注同上------variableMap.put("#Remarks#", replyFeedbackReq.getContent());
        String userId = queryUserId(pushMessageRequest.getPatientIdentityCardType(), pushMessageRequest.getPatientIdentityCardNumber());
        pushMessageRequest.setUserId(baseFeedback.getUserId());
        pushMessageRequest.setMsgVariableMap(variableMap);
        if ("1".equals(baseFeedback.getRoleType())) {
            // 居民
            pushMessageRequest.setNotificateType("sugg_tobe_repl");
            pushMessageRequest.setTemplateCode("SUGG_TOBE_REPL");
        } else {
            // 医生
            pushMessageRequest.setNotificateType("sugg_tobe_doctor_repl");
            pushMessageRequest.setTemplateCode("SUGG_TOBE_DOCTOR_REPL");
        }
        pushMessageRequest.setTenantId(PublicBusinessConst.TENANTID);
        messageSyncService.productionMessage(pushMessageRequest);

        return baseFeedback;
    }


    /*查询投诉建议列表*/
    @RpcService
    @Override
    public PageInfo queryFeedbackList(FeedbackListReq feedbackListReq) throws ControllerException {
        log.info("feedbackListReq============>"+ JSONUtils.writeValueAsString(feedbackListReq));
        List<String> classifyList = new ArrayList<>();
        if (!CommonUtils.isNull(feedbackListReq.getDocId())){
            if (feedbackListReq.getDocId().equals("e205a250-9d49-40f1-b02a-951edda75f4d") ||  feedbackListReq.getDocId().equals("ef2a3e3d-fb40-4839-a202-409071d9c7a2") ||  feedbackListReq.getDocId().equals("408e5aad-7825-432e-a41a-6e4cfeece7b3") || feedbackListReq.getDocId().equals("d80fa653-f64c-4637-9ae0-b800ef3f155c")){
                feedbackListReq.setQueryType((byte) 3);
            }
        }

        switch (feedbackListReq.getQueryType()) {
            //我的反馈列表
            case 1:
                if (StringUtils.isEmpty(feedbackListReq.getUserId())) {
                    throw new ServiceException("查询类型为我的反馈列表，用户主键不能为空");
                }
                break;
            //医生处理列表
            case 2:
                if (StringUtils.isEmpty(feedbackListReq.getDocId())) {
                    throw new ServiceException("查询类型为医生处理列表时，医生唯一码不能为空");
                }
                classifyList = docTeamFeedbackTypeDAO.getClassifyListByDoctorId(feedbackListReq.getDocId(), null);
                if (CollectionUtils.isEmpty(classifyList)) {
                    //该医生无任何权限，直接返回空
                    return null;
                    //return BaseRespUtil.setResultSuccess(new PageInfo());
                }
                //有权限，继续
                //有删选类型
                if (StringUtils.isNotEmpty(feedbackListReq.getClassify())) {
                    //查询的类型是医生所拥有的权限
                    if (classifyList.contains(feedbackListReq.getClassify())) {
                        classifyList = new ArrayList<>();
                        //只返回用户筛选的类型
                        classifyList.add(feedbackListReq.getClassify());
                    } else {
                        //查询的类型是医生所没有的权限，直接返回空
                        return null;
                        //return BaseRespUtil.setResultSuccess(new PageInfo());
                    }
                }
                //机构代码为空，就查询医生所在的团队，团队所在机构的数据
                if (CommonUtils.isEmpty(feedbackListReq.getOrganizationId())) {
                    ParamsOrgQo request = new ParamsOrgQo();
                    request.setDocId(feedbackListReq.getDocId());
                    //查询医生执业点的机构列表
                    List<Map<String, Object>> maps = organizationInfoService.queryOrganizationList(request);
                    if (CommonUtils.isNotEmpty(maps)) {
                        List<String> organizationIdList = new ArrayList<>();
                        for (Map<String, Object> map : maps) {
                            String organizationId = (String) map.get("organizationId");
                            String mainFlag = (String) map.get("mainFlag");
                            //只查询医生的主职业机构数据
                            if ("1".equals(mainFlag)) {
                                organizationIdList.add(organizationId);
                            }
                        }
                        feedbackListReq.setOrganizationIdList(organizationIdList);
                    }
                }
                break;
            //管理员处理列表
            case 3:
                if (StringUtils.isNotEmpty(feedbackListReq.getUserId()) || StringUtils.isNotEmpty(feedbackListReq.getDoctorId())) {
                    throw new ServiceException("查询类型为管理员处理列表时，用户主键,医生唯一码不能有值");
                    //return BaseRespUtil.setResultError("查询类型为管理员处理列表时，用户主键,医生唯一码不能有值");
                }
                if (StringUtils.isNotEmpty(feedbackListReq.getClassify())) {
                    //有删选类型
                    classifyList = new ArrayList<>();
                    classifyList.add(feedbackListReq.getClassify());
                    //只返回用户筛选的类型
                }
                break;
            default:
                throw new ServiceException("查询类型错误");
        }
        feedbackListReq.setClassifyList(classifyList);
        List<BaseFeedback> feedbackList = new ArrayList<>();
        Long count = baseFeedbackDAO.queryFeedbackListCount(feedbackListReq);
        if (count > 0) {
            feedbackList = baseFeedbackDAO.queryDocFeedbackList(feedbackListReq);
            if (!CollectionUtils.isEmpty(feedbackList)) {
                PageInfo pageInfo = new PageInfo(feedbackList);
                pageInfo.setPageNum(feedbackListReq.getPageNo());
                pageInfo.setPageSize(feedbackListReq.getPageSize());
                pageInfo.setTotal(count);
                return pageInfo;
            }
        }
        return new PageInfo();
    }


    /**
     * @description: 查询意见反馈数量
     * @author: chenJij@bsoft.com.cn
     * @date: 2020/9/22 18:20
     * @param: feedbackListReq
     * @return: java.util.Map<java.lang.String, java.lang.Object>
     */
    @Override
    @RpcService
    public Map<String, Object> queryFeedbackCount(FeedbackListReq feedbackListReq) throws ControllerException {
        Map<String, Object> map = new HashMap<>();
        long total = 0L;
        //查询医生所在团队所拥有的意见反馈类型列表
        List<String> classifyList = docTeamFeedbackTypeDAO.getClassifyListByDoctorId(feedbackListReq.getDocId(),
                feedbackListReq.getDoctorId());

        if (ObjectUtils.isEmpty(classifyList)|| classifyList.size()==0){
            return new HashMap<String, Object>() {{
                put("count",0L);
            }};
        }


        if (StringUtils.isNotEmpty(feedbackListReq.getClassify())) {
            //查询的类型是医生所拥有的权限
            if (classifyList.contains(feedbackListReq.getClassify())) {
                classifyList = new ArrayList<>();
                //只返回用户筛选的类型
                classifyList.add(feedbackListReq.getClassify());
            }
        }

        feedbackListReq.setClassifyList(classifyList);

        if (CommonUtils.isEmpty(feedbackListReq.getOrganizationId())) {
            ParamsOrgQo request = new ParamsOrgQo();
            request.setDocId(feedbackListReq.getDocId());
            //查询医生执业点的机构列表
            List<Map<String, Object>> maps =organizationInfoService.queryOrganizationList(request);
            if (CommonUtils.isNotEmpty(maps)) {
                List<String> organizationIdList = new ArrayList<>();
                for (Map<String, Object> mp : maps) {
                    String organizationId = (String) mp.get("organizationId");
                    String mainFlag = (String) mp.get("mainFlag");
                    //只查询医生的主职业机构数据
                    if ("1".equals(mainFlag)) {
                        organizationIdList.add(organizationId);
                    }
                }
                feedbackListReq.setOrganizationIdList(organizationIdList);
            }
        }
        //查询意见反馈类型数量
        Long count = baseFeedbackDAO.queryFeedbackListCount(feedbackListReq);

        if (null != count) {
            total = count.longValue();
        }
        map.put("count", total);

        return map;
    }

    private String queryUserId(String cardType, String cardId) {
        Certificate certificate = null;
        String userId = null;
        try {
            if (CommonUtils.isNotEmpty(cardType) && CommonUtils.isNotEmpty(cardId)) {
                certificate = new Certificate(IdentityTransformUtil.huLianIdentityToHcn(cardType), cardId, "01");
                if (hcn.util.CommonUtils.isNotNull(certificate)) {
                    Unique unique = mpiProvider.getUnique(certificate, hcn.common.Constants.USERID_SOURCE, hcn.common.Constants.USERID_TYPE_CODE);
                    if (null != unique) {
                        userId = SM4Utils.decryptData_ECB(unique.getUniqueId());
                    }
                }
            }
        } catch (MPIException e) {
            log.error("queryUserId出错:" + e.getMessage());
            e.printStackTrace();
        }
        return userId;
    }

    public AccessToken findUserTokenByUserId(String userId) {
        List<UserRoleToken> rs = null;
        AccessToken accessToken = null;
        try {
            User user = AccountCenter.getUser(userId);
            if (CommonUtils.isNotEmpty(user)) {
                Collection<UserRoleToken> tokens = user.getUserRoleTokens();
                rs = new ArrayList();
                Iterator var4 = tokens.iterator();

                while (var4.hasNext()) {
                    UserRoleToken ur = (UserRoleToken) var4.next();
                    rs.add(ur);
                }
                if (CommonUtils.isNotEmpty(rs)) {
                    accessToken = AppContextHolder.get().getBean(AccessTokenLoader.class).getByUser(rs.get(0).getUserId(), rs.get(0).getId(), rs.get(0).getDeptId());
                }
            }
        } catch (ControllerException e) {
            e.printStackTrace();
        }

        return accessToken;
    }

    public IMPIProvider getMpiProvider() {
        return mpiProvider;
    }

    public void setMpiProvider(IMPIProvider mpiProvider) {
        this.mpiProvider = mpiProvider;
    }

    /*查询单条投诉建议详情*/
    @RpcService
    @Override
    public BaseFeedback queryFeedbackDetail(BaseFeedback feedbackReq) {
        if (StringUtils.isEmpty(feedbackReq.getFeedbackId())) {
            throw new ServiceException("主键不能为空");
        }
        BaseFeedback feedback = baseFeedbackDAO.get(feedbackReq.getFeedbackId());
        if (feedback != null) {
            return feedback;
        } else {
            throw new ServiceException("查无ID为：" + feedbackReq.getFeedbackId() + "的记录");
        }
    }

}
